package org.springblade.tms.module.sap.base;

import io.seata.spring.annotation.GlobalTransactional;
import org.apache.logging.log4j.util.Strings;
import org.springblade.common.utils.EnumUtils;
import org.springblade.core.redis.lock.RedisLock;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.feign.IUserClient;
import org.springblade.tms.global.enums.*;
import org.springblade.tms.global.exception.SapException;
import org.springblade.tms.global.utils.CreateUserUtil;
import org.springblade.tms.global.utils.OrderNumUtil;
import org.springblade.tms.module.billing.entity.TMBilling;
import org.springblade.tms.module.billing.service.IBillingService;
import org.springblade.tms.module.billingitem.entity.TMBillingItem;
import org.springblade.tms.module.billingitem.service.IBillingItemService;
import org.springblade.tms.module.demandextrainfo.entity.TmDemandExtraInfo;
import org.springblade.tms.module.demandextrainfo.service.ITmDemandExtraInfoService;
import org.springblade.tms.module.demandorder.entity.TMDemandOrder;
import org.springblade.tms.module.demandorder.service.IDemandOrderService;
import org.springblade.tms.module.demandorderitem.entity.TMDemandOrderItem;
import org.springblade.tms.module.demandorderitem.service.IDemandOrderItemService;
import org.springblade.tms.module.exceptionreason.entity.TMExceptionReason;
import org.springblade.tms.module.exceptionreason.service.IExceptionReasonService;
import org.springblade.tms.module.exceptionrecord.entity.TMExceptionRecord;
import org.springblade.tms.module.exceptionrecord.service.IExceptionRecordService;
import org.springblade.tms.module.exceptiontype.entity.TMExceptionType;
import org.springblade.tms.module.exceptiontype.service.IExceptionTypeService;
import org.springblade.tms.module.gps.base.GPSRequestService;
import org.springblade.tms.module.gps.dto.GpsSignDTO;
import org.springblade.tms.module.inquirysheet.entity.TMInquirySheet;
import org.springblade.tms.module.inquirysheet.service.IInquirySheetService;
import org.springblade.tms.module.sap.dto.*;
import org.springblade.tms.module.statementorder.entity.TMStatementOrder;
import org.springblade.tms.module.statementorder.service.IStatementOrderService;
import org.springblade.tms.module.transportlinepoint.entity.TMTransportLinePoint;
import org.springblade.tms.module.transportlinepoint.service.ITransportLinePointService;
import org.springblade.tms.module.transportorder.entity.TMTransportOrder;
import org.springblade.tms.module.transportorder.service.ITransportOrderService;
import org.springblade.tms.module.transportorderitem.entity.TMTransportOrderItem;
import org.springblade.tms.module.transportorderitem.service.ITransportOrderItemService;
import org.springblade.tms.module.userinfo.entity.TMUserInfo;
import org.springblade.tms.module.userinfo.service.IUserInfoService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static org.springblade.tms.global.constant.RedisConstant.DEMAND_ORDER_SERIAL_Lock;
import static org.springblade.tms.global.constant.RedisConstant.DEMAND_ORDER_SERIAL_NUMBER;
import static org.springblade.tms.global.enums.UserTypeEnum.CARRIER;

/**
 * @author: yr
 * @className: SapService
 * @createDate: 2022/3/7
 * @description: spa接口服务
 */
@Service
@Transactional(rollbackFor = Exception.class)
@GlobalTransactional
public class SapService {
    @Resource
    private IUserInfoService userInfoService;
    @Resource
    private IUserClient userClient;
    @Resource
    private IDemandOrderItemService demandOrderItemService;
    @Resource
    private IDemandOrderService demandOrderService;
    @Resource
    private ITransportOrderService transportOrderService;
    @Resource
    private ITransportLinePointService transportLinePointService;
    @Resource
    private IExceptionRecordService exceptionRecordService;
    @Resource
    private IExceptionTypeService exceptionTypeService;
    @Resource
    private IExceptionReasonService exceptionReasonService;
    @Resource
    private IStatementOrderService statementOrderService;
    @Resource
    private IBillingService billingService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private GPSRequestService gpsRequestService;
    @Resource
    private ITransportOrderItemService transportOrderItemService;
    @Resource
    private IInquirySheetService iInquirySheetService;
    @Resource
    private IBillingItemService billingItemService;
    @Resource
    private ITmDemandExtraInfoService demandExtraInfoService;

    /**
     * @param carrierList
     * @return
     * @Desc 承运商基本信息接口服务
     * @author: yr
     * @createDate: 2022/3/7
     */
    public R carrierBasicInformation(List<Carrier> carrierList) {
        //将新增部分和修改部分分流处理
        List<String> partnerList = carrierList.stream().map(Carrier::getTmId).collect(Collectors.toList());
        //拿出修改部分
        List<TMUserInfo> userInfoList = userInfoService.lambdaQuery().in(TMUserInfo::getTmId, partnerList).list();
        List<String> tmIdList = userInfoList.stream().map(TMUserInfo::getTmId).collect(Collectors.toList());
        //拿出新增部分
        partnerList.removeAll(tmIdList);
        //修改userinfo表数据
        for (TMUserInfo userInfo : userInfoList) {
            for (Carrier carrier : carrierList) {
                if (userInfo.getTmId().equals(carrier.getTmId())) {
                    BeanUtil.copy(carrier, userInfo);
                    break;
                }
            }
        }
        //修改用户服务user
        for (TMUserInfo tmUserInfo : userInfoList) {
            R<User> userR = userClient.userInfoById(tmUserInfo.getParentId());
            User user = CreateUserUtil.updateUser(tmUserInfo, userR.getData());
            R<Boolean> updateUser = userClient.updateUser(user);
            if (!updateUser.isSuccess()) {
                throw SapException.throwCommonException(updateUser.getMsg());
            }
        }
        userInfoService.updateBatchById(userInfoList);
        //新增部分
        List<TMUserInfo> tmUserInfos = new ArrayList<>();
        for (Carrier carrier : carrierList) {
            for (String partner : partnerList) {
                if (carrier.getTmId().equals(partner)) {
                    tmUserInfos.add(BeanUtil.copy(carrier, TMUserInfo.class));
                    break;
                }
            }
        }
        tmUserInfos.forEach(tmUser -> tmUser.setApprovalStatus(ApprovalStatusEnum.PENDING_SUBMISSION.getValue()));
        //在用户服务新增用户
        for (TMUserInfo tmUser : tmUserInfos) {
            tmUser.setUserType(CARRIER.getValue());
            User user = CreateUserUtil.createUser(tmUser);

            R<String> stringR = userClient.saveUserAndGetID(user);
            if (!stringR.isSuccess()) {
                throw SapException.throwCommonException(stringR.getMsg());
            }
            Long id = Long.valueOf(stringR.getData());
            tmUser.setParentId(id);
        }
        userInfoService.saveBatch(tmUserInfos);
        return R.status(true);
    }

    /**
     * @param demandListDtoList:
     * @return R
     * @author yr
     * @description 需求单数据
     * @date 2022/3/14 10:07
     */
    @RedisLock(DEMAND_ORDER_SERIAL_Lock + "requestOrderData")
    public R requestOrderData(List<DemandListDto> demandListDtoList) {
        demandListDtoList.forEach(demandListDto -> {
            demandListDto.setOrderNo(demandListDto.getTorId().toString());
            demandListDto.setDeliverNo(demandListDto.getLaveltxt().toString());
            demandListDto.setOrderNumber(demandListDto.getOrigBtdId().toString());
        });
        //通过承运商编码获取承运商id
        List<String> carrierNos = demandListDtoList.stream().map(DemandListDto::getCarrierNo).collect(Collectors.toList());
        List<TMUserInfo> tmUserInfos = userInfoService.lambdaQuery().in(TMUserInfo::getTmId, carrierNos).list();
        Map<String, Long> idByTmId = tmUserInfos
                .stream().collect(Collectors.toMap(TMUserInfo::getTmId, TMUserInfo::getId));
        LinkedList<TMDemandOrder> demandOrderList = new LinkedList<>();
        //验证承运商资质是否到期
//		List<TMUserInfo> userInfos = tmUserInfos.stream().filter(tmUserInfo ->
//			System.currentTimeMillis() < Instant.from(tmUserInfo.getCertificateTransportValidDateEnd().atZone(ZoneId.systemDefault())).toEpochMilli()
//				|| System.currentTimeMillis() < Instant.from(tmUserInfo.getCertificateOperationValidDateEnd().atZone(ZoneId.systemDefault())).toEpochMilli())
//			.collect(Collectors.toList());
//		if (userInfos != null && userInfos.isEmpty()) {
//			List<String> names = userInfos.stream().map(TMUserInfo::getName).collect(Collectors.toList());
//			String join = Func.join(names, ",");
//			SapException.throwCommonException(join + "的资质已过期");
//		}
//		List<TMUserInfo> tmUserInfoList = tmUserInfos.stream().filter(tmUserInfo -> tmUserInfo.getApprovalStatus().equals(ApprovalStatusEnum.PASSED.getValue()))
//			.collect(Collectors.toList());
//		if (tmUserInfoList != null && tmUserInfoList.isEmpty()) {
//			List<String> names = userInfos.stream().map(TMUserInfo::getName).collect(Collectors.toList());
//			String join = Func.join(names, ",");
//			SapException.throwCommonException(join + "的资质审核未通过");
//		}
        for (DemandListDto demandListDto : demandListDtoList) {
            TMDemandOrder tmDemandOrder = BeanUtil.copy(demandListDto, TMDemandOrder.class);
            tmDemandOrder.setCarrierId(idByTmId.get(demandListDto.getCarrierNo()));
            demandOrderList.add(tmDemandOrder);
        }
        //获取可修改或新增的需求单的货运订单号
        List<String> demandOrderIds = demandOrderList.stream().map(TMDemandOrder::getOrderNo).collect(Collectors.toList());
        //查询需求单下是否有运单
        List<TMTransportOrder> transportOrderList = transportOrderService.lambdaQuery()
                .in(!demandOrderIds.isEmpty(), TMTransportOrder::getOrderNo, demandOrderIds)
                .ne(TMTransportOrder::getTransportStatus, WaybillStatusEnum.ABOLISHED.getValue())
                .apply(demandOrderIds.isEmpty(), "1=2")
                .select(TMTransportOrder::getDemandId).list();
        List<String> transportIds = transportOrderList.stream().map(TMTransportOrder::getOrderNo).collect(Collectors.toList());
        transportIds = transportIds.stream().distinct().collect(Collectors.toList());
        //排除有运单的部分需求单
        demandOrderIds.removeAll(transportIds);
        //需求单已存在，只需要修改的部分需求单
        List<TMDemandOrder> tmDemandOrderList = demandOrderService.lambdaQuery()
                .select(TMDemandOrder::getOrderNo, TMDemandOrder::getId)
                .in(!demandOrderIds.isEmpty(), TMDemandOrder::getOrderNo, demandOrderIds)
                .apply(demandOrderIds.isEmpty(), "1=2").list();

        //获取需要修改部分的货运订单号
        List<String> list = tmDemandOrderList.stream().map(TMDemandOrder::getOrderNo).collect(Collectors.toList());
        //通过货运订单号获取需要修改的需求单
        LinkedList<TMDemandOrder> demandOrderList1 = new LinkedList<>();
        for (TMDemandOrder tmDemandOrder : demandOrderList) {
            if (list.contains(tmDemandOrder.getOrderNo())) {
                demandOrderList1.add(tmDemandOrder);
            }
        }
        //获取需要修改部分的需求单id
        Map<String, Long> idMap = tmDemandOrderList.stream().collect(Collectors.toMap(TMDemandOrder::getOrderNo, TMDemandOrder::getId));
        for (TMDemandOrder tmDemandOrder : demandOrderList1) {
            tmDemandOrder.setId(idMap.get(tmDemandOrder.getOrderNo()));
        }
        demandOrderList1.forEach(tmDemandOrder -> {
            tmDemandOrder.setDemandStatus(DemandStatusEnum.ALREADY.value());
        });
        demandOrderService.updateBatchById(demandOrderList1);
        //获取需要新增的部分需求单
        demandOrderIds.removeAll(list);
        LinkedList<TMDemandOrder> demandOrderList2 = new LinkedList<>();
        for (TMDemandOrder tmDemandOrder : demandOrderList) {
            if (demandOrderIds.contains(tmDemandOrder.getOrderNo())) {
                tmDemandOrder.setDemandStatus(DemandStatusEnum.ALREADY.value());
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                Date date = new Date();
                if (!redisTemplate.hasKey(DEMAND_ORDER_SERIAL_NUMBER)) {
                    redisTemplate.opsForValue().set(DEMAND_ORDER_SERIAL_NUMBER, "0001");
                }
                String serialNumber = redisTemplate.opsForValue().get(DEMAND_ORDER_SERIAL_NUMBER);
                tmDemandOrder.setDemandOrderNumber(new StringBuilder(EnumUtils.getEnumByValue(WerksCodeEnum.class, tmDemandOrder.getWerks()).get().getDescription())
                        .append(WerksCodeEnum.XQD.getValue()).append(format.format(date).replace("-", ""))
                        .append(serialNumber).toString());
                String addNum = OrderNumUtil.addNum(serialNumber);
                redisTemplate.opsForValue().getAndSet(DEMAND_ORDER_SERIAL_NUMBER, addNum);
                demandOrderList2.add(tmDemandOrder);
            }
        }
        demandOrderService.saveBatch(demandOrderList2);
        //新增后获取新增需求单id
        Map<String, Long> idMap1 = demandOrderService.lambdaQuery().in(!demandOrderIds.isEmpty(), TMDemandOrder::getOrderNo, demandOrderIds)
                .apply(demandOrderIds.isEmpty(), "1=2").list()
                .stream().collect(Collectors.toMap(TMDemandOrder::getOrderNo, TMDemandOrder::getId));
        //获取需要新增和修改的需求单明细
        LinkedList<TMDemandOrderItem> demandOrderItemList = new LinkedList<>();//修改部分
        LinkedList<TMDemandOrderItem> demandOrderItemList1 = new LinkedList<>();//新增部分
        //去掉存在运单的部分
        List<String> orderNoList = demandListDtoList.stream().map(DemandListDto::getOrderNo).collect(Collectors.toList());
        orderNoList.removeAll(transportIds);
        //获取行项目号
        ArrayList<String> itemNoList = new ArrayList<>();
        for (DemandListDto demandListDto : demandListDtoList) {
            for (DemandListItemDto demandListItemDto : demandListDto.getItem()) {
                itemNoList.add(demandListItemDto.getItemNo());
            }
        }
        List<TMDemandOrderItem> tmDemandOrderItems = demandOrderItemService.lambdaQuery().in(!itemNoList.isEmpty(), TMDemandOrderItem::getItemNo, itemNoList).list();
        Map<Long, List<TMDemandOrderItem>> demandOrderIdsMap = tmDemandOrderItems.stream().collect(Collectors.groupingBy(TMDemandOrderItem::getParentId));
        for (DemandListDto demandListDto : demandListDtoList) {
            if (orderNoList.contains(demandListDto.getOrderNo())) {
                //获取需要修改部分行项目的id
                List<TMDemandOrderItem> demandOrderItems = demandOrderIdsMap.get(idMap.get(demandListDto.getOrderNo()));
                Map<String, Long> itemIdMap = new LinkedHashMap<>();
                if (demandOrderItems != null && !demandOrderItems.isEmpty()) {
                    itemIdMap = demandOrderItems.stream().collect(Collectors.toMap(TMDemandOrderItem::getItemNo, TMDemandOrderItem::getId));
                }
                for (DemandListItemDto demandListItemDto : demandListDto.getItem()) {
                    TMDemandOrderItem tmDemandOrderItem = BeanUtil.copy(demandListItemDto, TMDemandOrderItem.class);
                    if (idMap.get(demandListDto.getOrderNo()) != null && !itemIdMap.isEmpty()) {
                        tmDemandOrderItem.setId(itemIdMap.get(tmDemandOrderItem.getItemNo()));
                        tmDemandOrderItem.setOriginNum(tmDemandOrderItem.getNum());
                        demandOrderItemList.add(tmDemandOrderItem);
                    } else {
                        tmDemandOrderItem.setOriginNum(tmDemandOrderItem.getNum());
                        demandOrderItemList1.add(tmDemandOrderItem);
                        tmDemandOrderItem.setParentId(idMap1.get(demandListDto.getOrderNo()));
                    }
                }
            }
        }
        demandOrderItemService.updateBatchById(demandOrderItemList);
        demandOrderItemService.saveBatch(demandOrderItemList1);
        //新增部分需求单新增补充信息
        List<TMDemandOrder> tmDemandOrdersSave = demandOrderList2.stream().filter(tmDemandOrder -> {
            return Strings.isNotBlank(tmDemandOrder.getBillOfLadingNumber());
        }).collect(Collectors.toList());
        List<TmDemandExtraInfo> tmDemandExtraInfos = new ArrayList<>();
        tmDemandOrdersSave.forEach(tmDemandOrder -> {
            TmDemandExtraInfo tmDemandExtraInfo = TmDemandExtraInfo.builder()
                    .deliverNo(tmDemandOrder.getBillOfLadingNumber())
                    .parentId(tmDemandOrder.getId())
                    .build();
            tmDemandExtraInfos.add(tmDemandExtraInfo);
        });
        //修改部分需求单补充信息处理
        List<Long> demandExtraInfoParentIds = demandOrderList1.stream().map(TMDemandOrder::getId).collect(Collectors.toList());
        List<TmDemandExtraInfo> demandExtraInfos = demandExtraInfoService.lambdaQuery()
                .in(demandExtraInfoParentIds != null && !demandExtraInfoParentIds.isEmpty(), TmDemandExtraInfo::getParentId, demandExtraInfoParentIds)
                .apply(demandExtraInfoParentIds == null && demandExtraInfoParentIds.isEmpty(), "1=2")
                .list();
        Map<Long, List<TmDemandExtraInfo>> demandExtraInfoByParentId = demandExtraInfos.stream().collect(Collectors.groupingBy(TmDemandExtraInfo::getParentId));
        demandOrderList1.forEach(tmDemandOrder -> {
            List<TmDemandExtraInfo> demandExtraInfoList = demandExtraInfoByParentId.get(tmDemandOrder.getId());
            if (demandExtraInfoList == null || demandExtraInfoList.isEmpty()) {
                TmDemandExtraInfo tmDemandExtraInfo = TmDemandExtraInfo.builder()
                        .deliverNo(tmDemandOrder.getBillOfLadingNumber())
                        .parentId(tmDemandOrder.getId())
                        .build();
                tmDemandExtraInfos.add(tmDemandExtraInfo);
            } else {
                demandExtraInfoList.forEach(tmDemandExtraInfo -> {
                    tmDemandExtraInfo.setDeliverNo(tmDemandOrder.getBillOfLadingNumber());
                });
                tmDemandExtraInfos.addAll(demandExtraInfoList);
            }
        });
        //新增或修改需求单补充信息
        demandExtraInfoService.saveOrUpdateBatch(tmDemandExtraInfos);
        if (transportIds.isEmpty()) {
            return R.status(true);
        } else {
            throw SapException.throwCommonException(transportIds + "部分需求单已存在运单");
        }
    }


    /**
     * @param updateWaybillDTO:
     * @return SapData
     * @author yr
     * @description 运单更新
     * @date 2022/3/28 15:02
     */
    public R waybillUpdate(UpdateWaybillDTO updateWaybillDTO) {
        //运单日志
        ArrayList<TMTransportLinePoint> tmTransportLinePoints = new ArrayList<>();
        //异常记录
        ArrayList<TMExceptionRecord> exceptionRecords = new ArrayList<>();
        //获取运单和需求单
        Map<String, List<TMDemandOrder>> tmDemandOrderMap = new HashMap<>();
        List<TMDemandOrder> tmDemandOrderList = new ArrayList<>();
        List<TMTransportOrder> tmTransportOrderList = new ArrayList<>();
        Map<String, List<TMTransportOrder>> tmTransportOrderMap = new HashMap<>();
        if (!updateWaybillDTO.getType().equals(EventTypeEnum.FSD.getValue())) {
            List<Long> torIds = updateWaybillDTO.getSapUpdateWaybillDTO().stream().map(SapUpdateWaybillDTO::getTorId).collect(Collectors.toList());
            tmDemandOrderList = demandOrderService.lambdaQuery()
                    .ne(TMDemandOrder::getDemandStatus, DemandStatusEnum.ABOLISHED.value())
                    .in(!torIds.isEmpty(), TMDemandOrder::getOrderNo, torIds)
                    .apply(torIds.isEmpty(), "1=2").list();
            tmDemandOrderMap = tmDemandOrderList.stream().collect(Collectors.groupingBy(TMDemandOrder::getOrderNo));
            tmTransportOrderList = transportOrderService.lambdaQuery()
                    .in(!torIds.isEmpty(), TMTransportOrder::getOrderNoNew, torIds)
                    .ne(TMTransportOrder::getTransportStatus, WaybillStatusEnum.ABOLISHED.value())
                    .apply(torIds.isEmpty(), "1=2").list();
            if (tmDemandOrderList.isEmpty() && tmTransportOrderList.isEmpty()) {
                SapException.throwCommonException("该需求单或运单不存在");
            }
            tmTransportOrderMap = tmTransportOrderList.stream().collect(Collectors.groupingBy(TMTransportOrder::getOrderNoNew));
        }
        //更新类型判断
        if (updateWaybillDTO.getType().equals(EventTypeEnum.EVENT.getValue())) {
            //事件更新后需要更新状态的需求单和运输单
            List<TMDemandOrder> updateDemandOrderList = new ArrayList<>();
            List<TMTransportOrder> updateTransportOrderList = new ArrayList<>();
            //需求单或运输单判断
            for (SapUpdateWaybillDTO sapUpdateWaybillDTO : updateWaybillDTO.getSapUpdateWaybillDTO()) {
                if (sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFB1.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFB2.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFO9.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFO3.getValue())
                ) {
                    TMDemandOrder tmDemandOrder = tmDemandOrderMap.get(sapUpdateWaybillDTO.getTorId().toString()).get(0);
                    //异常汇报单独处理
                    if (sapUpdateWaybillDTO.getEventCode().equals(EventCodeEnum.ExceptionReport.getValue())) {
                        exceptionPush(exceptionRecords, sapUpdateWaybillDTO, tmDemandOrder.getId(), tmDemandOrder.getDemandStatus(), OrderTypeEnum.DEMAND_LIST.value());
                    } else {
                        String eventCode = sapUpdateWaybillDTO.getEventCode();
                        if (eventCode.equals(EventCodeEnum.ARRIVE_AT_THE_PICK_UP_POINT.getValue())) {
                            if (!tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.TO_BE_LOADED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.TO_BE_SHIPPED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.AWAITING_DELIVERY.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.FINISH.value())) {
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.ARRIVE_AT_THE_PICK_UP_POINT.getDescription(), tmDemandOrder.getId());
                                tmDemandOrder.setDemandStatus(DemandStatusEnum.TO_BE_LOADED.value());

                            }
                        } else if (eventCode.equals(EventCodeEnum.START_LOADING.getValue())) {
                            if (tmDemandOrder.getDemandStatus().equals(WaybillStatusEnum.LOADED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(WaybillStatusEnum.ARRIVE_AT_THE_TRANSFER_STATION.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(WaybillStatusEnum.SHIPPED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(WaybillStatusEnum.ARRIVED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                tmDemandOrder.setDemandStatus(WaybillStatusEnum.LOADED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.START_LOADING.getDescription(), tmDemandOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.LOADED.getValue())) {
                            if (!tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.TO_BE_SHIPPED.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.AWAITING_DELIVERY.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.FINISH.value())) {
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.LOADED.getDescription(), tmDemandOrder.getId());
                                tmDemandOrder.setDemandStatus(DemandStatusEnum.TO_BE_SHIPPED.value());
                            }
                        } else if (eventCode.equals(EventCodeEnum.SHIPPED.getValue())) {
                            if (!tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.AWAITING_DELIVERY.value()) &
                                    !tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.FINISH.value())) {
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.SHIPPED.getDescription(), tmDemandOrder.getId());
                                tmDemandOrder.setDemandStatus(DemandStatusEnum.AWAITING_DELIVERY.value());
                            }
                        } else if (eventCode.equals(EventCodeEnum.COMPLETED.getValue())) {
                            if (!tmDemandOrder.getDemandStatus().equals(DemandStatusEnum.FINISH.value())) {
                                tmDemandOrder.setDemandStatus(DemandStatusEnum.FINISH.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.COMPLETED.getDescription(), tmDemandOrder.getId());
                            }
                        }


                    }
                    //修改需求单状态
                    updateDemandOrderList.add(tmDemandOrder);
                } else {
                    TMTransportOrder tmTransportOrder = tmTransportOrderMap.get(sapUpdateWaybillDTO.getTorId().toString()).get(0);
                    //异常汇报单独处理
                    if (sapUpdateWaybillDTO.getEventCode().equals(EventCodeEnum.ExceptionReport.getValue())) {
                        exceptionPush(exceptionRecords, sapUpdateWaybillDTO, tmTransportOrder.getId(), tmTransportOrder.getTransportStatus(), OrderTypeEnum.SINGLE_TRANSPORT.value());
                    } else {
                        String eventCode = sapUpdateWaybillDTO.getEventCode();
                        if (eventCode.equals(EventCodeEnum.LOADED.getValue())) {
                            if (tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.LOADED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.LOADED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.LOADED.getDescription(), tmTransportOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.START_UNLOADING.getValue())) {
                            if (tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ARRIVED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.ARRIVED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.START_UNLOADING.getDescription(), tmTransportOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.FACTORY.getValue())) {
                            if (tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.COMPLETED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.FACTORY.getDescription(), tmTransportOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.START_LOADING.getValue())) {
                            if (tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.LOADED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.LOADED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.START_LOADING.getDescription(), tmTransportOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.ARRIVE_AT_THE_PICK_UP_POINT.getValue())) {
                            if (!tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.LOADED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ARRIVE_AT_THE_TRANSFER_STATION.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.SHIPPED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ARRIVED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.LOADED.value());
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.ARRIVE_AT_THE_PICK_UP_POINT.getDescription(), tmTransportOrder.getId());
                                GpsSignDTO gpsSignDTO = new GpsSignDTO();
                                gpsSignDTO.setConsigNo(tmTransportOrder.getTransportNo());
                                gpsSignDTO.setSignTime(LocalDateTime.now());
                                gpsSignDTO.setSignStatus("1");
                                List<TMTransportOrderItem> list = transportOrderItemService.lambdaQuery().eq(TMTransportOrderItem::getParentId, tmTransportOrder.getId()).list();
                                BigDecimal num = list.stream().map(TMTransportOrderItem::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
                                gpsSignDTO.setSignWeight(num);
//                                gpsRequestService.sign(gpsSignDTO);
                            }
                        } else if (eventCode.equals(EventCodeEnum.SHIPPED.getValue())) {
                            if (!tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.SHIPPED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ARRIVED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                if (tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO4.getValue()) || tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFOA.getValue())
                                        || tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO5.getValue()) || tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFOB.getValue())) {

                                    tmTransportOrder.setTransportStatus(WaybillStatusEnum.ARRIVE_AT_THE_TRANSFER_STATION.value());
                                    //日志写入
                                } else {
                                    tmTransportOrder.setTransportStatus(WaybillStatusEnum.SHIPPED.value());
                                    //日志写入
                                }
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.SHIPPED.getDescription(), tmTransportOrder.getId());

                            }
                        } else if (eventCode.equals(EventCodeEnum.DELIVERED.getValue())) {
                            if (!tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.ARRIVED.value()) &
                                    !tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                if (tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO2) && tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO8)) {
                                    tmTransportOrder.setTransportStatus(WaybillStatusEnum.COMPLETED.value());
                                } else {
                                    tmTransportOrder.setTransportStatus(WaybillStatusEnum.ARRIVED.value());
                                }
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.DELIVERED.getDescription(), tmTransportOrder.getId());
                            }
                        } else if (eventCode.equals(EventCodeEnum.COMPLETED.getValue()) || eventCode.equals(EventCodeEnum.UNLOADED.getValue())) {
                            if (!tmTransportOrder.getTransportStatus().equals(WaybillStatusEnum.COMPLETED.value())) {
                                tmTransportOrder.setTransportStatus(WaybillStatusEnum.COMPLETED.value());
                                GpsSignDTO gpsSignDTO = new GpsSignDTO();
                                gpsSignDTO.setConsigNo(tmTransportOrder.getTransportNo());
                                gpsSignDTO.setSignTime(LocalDateTime.now());
                                gpsSignDTO.setSignStatus("2");
                                List<TMTransportOrderItem> list = transportOrderItemService.lambdaQuery().eq(TMTransportOrderItem::getParentId, tmTransportOrder.getId()).list();
                                BigDecimal num = list.stream().map(TMTransportOrderItem::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
                                gpsSignDTO.setSignWeight(num);
//                                gpsRequestService.sign(gpsSignDTO);
                                //日志写入
                                addTransportLinePoint(tmTransportLinePoints, sapUpdateWaybillDTO, EventCodeEnum.COMPLETED.getDescription(), tmTransportOrder.getId());
                            }
                        }

                    }
                    //修改运单状态
                    updateTransportOrderList.add(tmTransportOrder);
                }

            }
            //存日志
            if (!tmTransportLinePoints.isEmpty()) {
                transportLinePointService.saveBatch(tmTransportLinePoints);
            }
            //新增异常汇报
            if (!exceptionRecords.isEmpty()) {
                exceptionRecordService.saveBatch(exceptionRecords);
            }
            if (!updateTransportOrderList.isEmpty()) {
                transportOrderService.updateBatchById(updateTransportOrderList);
            }
            if (!updateDemandOrderList.isEmpty()) {
                demandOrderService.updateBatchById(updateDemandOrderList);
            }
            //修改运费
        } else if (updateWaybillDTO.getType().equals(EventTypeEnum.CHARGES.getValue())) {
            List<TMStatementOrder> statementOrderUpdateList = new ArrayList<>();
            List<TMStatementOrder> statementOrderSaveList = new ArrayList<>();
            List<Long> demandOrderIds = tmDemandOrderList.stream().map(TMDemandOrder::getId).collect(Collectors.toList());
            List<Long> transportOrderIds = tmTransportOrderList.stream().map(TMTransportOrder::getId).collect(Collectors.toList());
            Map<Long, List<TMStatementOrder>> statementOrderMap = statementOrderService.lambdaQuery()
                    .and(tmStatementOrderLambdaQueryWrapper -> tmStatementOrderLambdaQueryWrapper.in(!demandOrderIds.isEmpty(), TMStatementOrder::getParentId, demandOrderIds)
                            .or().in(!transportOrderIds.isEmpty(), TMStatementOrder::getParentId, transportOrderIds))
                    .apply(demandOrderIds.isEmpty(), "1=2")
                    .list().stream().collect(Collectors.groupingBy(TMStatementOrder::getParentId));
            for (SapUpdateWaybillDTO sapUpdateWaybillDTO : updateWaybillDTO.getSapUpdateWaybillDTO()) {
                if (sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFB1.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFB2.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFO9.getValue()) ||
                        sapUpdateWaybillDTO.getTorType().equals(TorTypeEnum.ZFO3.getValue())
                ) {
                    TMDemandOrder tmDemandOrder = tmDemandOrderMap.get(sapUpdateWaybillDTO.getTorId().toString()).get(0);
                    //新增或修改需求单运费
                    if (statementOrderMap.get(tmDemandOrder.getId()) != null
                            && (statementOrderMap.get(tmDemandOrder.getId()).stream()
                            .collect(Collectors.groupingBy(TMStatementOrder::getChargeText))
                            .get(sapUpdateWaybillDTO.getChargeText())) != null) {
                        for (TMStatementOrder tmStatementOrder : statementOrderMap.get(tmDemandOrder.getId()).stream()
                                .collect(Collectors.groupingBy(TMStatementOrder::getChargeText))
                                .get(sapUpdateWaybillDTO.getChargeText())) {
                            if (Strings.isBlank(tmStatementOrder.getNo())) {
                                if (tmStatementOrder.getParentId().equals(tmDemandOrder.getId())) {
                                    tmStatementOrder.setMoney(sapUpdateWaybillDTO.getMoney());
                                    tmStatementOrder.setStaging(false);
                                    tmStatementOrder.setDocCurrency(sapUpdateWaybillDTO.getDocCurrency());
                                    statementOrderUpdateList.add(tmStatementOrder);
                                }
                            } else {
                                throw SapException.throwCommonException("已确认运费不可修改");
                            }
                        }
                    } else {
                        TMStatementOrder statementOrder = new TMStatementOrder();
                        statementOrder.setMoney(sapUpdateWaybillDTO.getMoney());
                        statementOrder.setChargeType(sapUpdateWaybillDTO.getChargeType());
                        statementOrder.setChargeText(sapUpdateWaybillDTO.getChargeText());
                        statementOrder.setOrderType(OrderTypeEnum.DEMAND_LIST.value());
                        statementOrder.setParentId(tmDemandOrder.getId());
                        statementOrder.setStaging(false);
                        statementOrder.setDocCurrency(sapUpdateWaybillDTO.getDocCurrency());
                        statementOrder.setCarrierNo(tmDemandOrder.getCarrierNo());
                        statementOrder.setContractCompany(tmDemandOrder.getContractCompany());
                        statementOrderSaveList.add(statementOrder);
                    }
                } else {
                    TMTransportOrder tmTransportOrder = tmTransportOrderMap.get(sapUpdateWaybillDTO.getTorId().toString()).get(0);
                    //新增或修改运单运费
                    if (statementOrderMap.get(tmTransportOrder.getId()) != null
                            && (statementOrderMap.get(tmTransportOrder.getId()).stream()
                            .collect(Collectors.groupingBy(TMStatementOrder::getChargeText))
                            .get(sapUpdateWaybillDTO.getChargeText())) != null) {
                        for (TMStatementOrder tmStatementOrder : statementOrderMap.get(tmTransportOrder.getId()).stream()
                                .collect(Collectors.groupingBy(TMStatementOrder::getChargeText))
                                .get(sapUpdateWaybillDTO.getChargeText())) {
                            if (Strings.isBlank(tmStatementOrder.getNo())) {
                                if (tmStatementOrder.getParentId().equals(tmTransportOrder.getId())) {
                                    tmStatementOrder.setMoney(sapUpdateWaybillDTO.getMoney());
                                    tmStatementOrder.setDocCurrency(sapUpdateWaybillDTO.getDocCurrency());
                                    tmStatementOrder.setStaging(false);
                                    statementOrderUpdateList.add(tmStatementOrder);
                                }
                            } else {
                                throw SapException.throwCommonException("已确认运费不可修改");
                            }
                        }
                    } else {
                        TMStatementOrder statementOrder = new TMStatementOrder();
                        statementOrder.setMoney(sapUpdateWaybillDTO.getMoney());
                        statementOrder.setChargeType(sapUpdateWaybillDTO.getChargeType());
                        statementOrder.setChargeText(sapUpdateWaybillDTO.getChargeText());
                        statementOrder.setOrderType(OrderTypeEnum.SINGLE_TRANSPORT.value());
                        statementOrder.setParentId(tmTransportOrder.getId());
                        statementOrder.setCarrierNo(tmTransportOrder.getCarrierNo());
                        statementOrder.setStaging(false);
                        statementOrder.setContractCompany(tmTransportOrder.getContractCompany());
                        statementOrder.setDocCurrency(sapUpdateWaybillDTO.getDocCurrency());
                        if (tmTransportOrder.getOrderType().equals(TorTypeEnum.ZFO6.getValue())) {
                            statementOrder.setFsdPost("X");
                        }
                        statementOrderSaveList.add(statementOrder);
                    }

                }
            }
            statementOrderService.updateBatchById(statementOrderUpdateList);
            statementOrderService.saveBatch(statementOrderSaveList);
        } else if (updateWaybillDTO.getType().equals(EventTypeEnum.FSD.getValue())) {
            //修改后的预结算单
            List<TMStatementOrder> updateStatementOrderList = new ArrayList<>();
            List<TMBilling> updateBillList = new ArrayList<>();
            List<TMBilling> deleteBillList = new ArrayList<>();
            //查询结算单
            List<String> sfirIds = updateWaybillDTO.getSapUpdateWaybill().stream().map(SapUpdateWaybillDTO::getSfirId).collect(Collectors.toList());
            List<TMBilling> tmBillings = billingService.lambdaQuery().in(TMBilling::getNo, sfirIds).list();
            Map<String, List<TMBilling>> billingMap = tmBillings.stream().collect(Collectors.groupingBy(TMBilling::getNo));
            List<TMStatementOrder> tmStatementOrders = statementOrderService.lambdaQuery().in(TMStatementOrder::getNo, sfirIds).list();
            Map<String, List<TMStatementOrder>> TMStatementOrderMap = tmStatementOrders.stream().collect(Collectors.groupingBy(TMStatementOrder::getNo));
            for (SapUpdateWaybillDTO sapUpdateWaybillDTO : updateWaybillDTO.getSapUpdateWaybill()) {
                List<TMStatementOrder> statementOrderList = TMStatementOrderMap.get(sapUpdateWaybillDTO.getSfirId());
                List<TMBilling> billingList = billingMap.get(sapUpdateWaybillDTO.getSfirId());
                if (billingList == null || statementOrderList == null) {
                    continue;
                }
                if (Strings.isNotBlank(sapUpdateWaybillDTO.getFsdDelete()) && sapUpdateWaybillDTO.getFsdDelete().equals("1")) {
                    statementOrderList.forEach(tmStatementOrder -> tmStatementOrder.setNo(""));
                    deleteBillList.addAll(billingList);
                } else {
                    billingList.forEach(tmBilling -> {
                        tmBilling.setPayStatus(sapUpdateWaybillDTO.getFsdPost());
                        tmBilling.setPostingDate(LocalDateTime.now());
                    });
                    updateBillList.addAll(billingList);
                }
                updateStatementOrderList.addAll(statementOrderList);
            }
            if (!deleteBillList.isEmpty()) {
                List<TMBillingItem> tmBillingItems = billingItemService.lambdaQuery()
                        .in(TMBillingItem::getBillingId, deleteBillList.stream().map(TMBilling::getNo).collect(Collectors.toList())).list();
                if (!tmBillingItems.isEmpty()) {
                    billingItemService.deleteLogic(tmBillingItems.stream().map(TMBillingItem::getId).collect(Collectors.toList()));
                }
                billingService.deleteLogic(deleteBillList.stream().map(TMBilling::getId).collect(Collectors.toList()));
            }
            if (!updateBillList.isEmpty()) {
                billingService.updateBatchById(updateBillList);
            }
            updateStatementOrderList.forEach(updateBill -> {
                updateBill.setStaging(false);
            });
            statementOrderService.updateBatchById(updateStatementOrderList);
        }
        return R.status(true);
    }

    //写入日志
    private void addTransportLinePoint(ArrayList<TMTransportLinePoint> tmTransportLinePoints, SapUpdateWaybillDTO sapUpdateWaybillDTO, String value, Long id) {
        //日志写入
        TMTransportLinePoint tmTransportLinePoint = new TMTransportLinePoint();
        tmTransportLinePoint.setParentId(id);
        tmTransportLinePoint.setTransport(value);
        tmTransportLinePoint.setCreateTime(sapUpdateWaybillDTO.getEventTime());
        tmTransportLinePoints.add(tmTransportLinePoint);
    }


    /**
     * @param exceptionRecords:异常记录list
     * @param sapUpdateWaybillDTO:
     * @param id:                       需求单或运单id
     * @param status:需求单或运单状态
     * @return void
     * @author yr
     * @description 异常封装
     * @date 2022/4/18 18:11
     */
    private void exceptionPush(ArrayList<TMExceptionRecord> exceptionRecords, SapUpdateWaybillDTO sapUpdateWaybillDTO, Long id, String status, String type) {
        TMExceptionRecord tmExceptionRecord = new TMExceptionRecord();
        TMExceptionType tmExceptionType = exceptionTypeService.lambdaQuery().eq(TMExceptionType::getEventReasonCode, sapUpdateWaybillDTO.getExceptionType()).one();
        tmExceptionRecord.setExceptionType(tmExceptionType.getId());
        if (Strings.isNotBlank(sapUpdateWaybillDTO.getEventReasonCode())) {
            TMExceptionReason tmExceptionReason = exceptionReasonService.lambdaQuery().eq(TMExceptionReason::getReasonCode, sapUpdateWaybillDTO.getEventReasonCode())
                    .eq(TMExceptionReason::getParentId, tmExceptionType.getId()).one();
            tmExceptionRecord.setExceptionTypeDesc(tmExceptionReason.getId());

        }
        tmExceptionRecord.setOrderType(type);
        tmExceptionRecord.setExceptionDate(sapUpdateWaybillDTO.getExceptionDate());
        tmExceptionRecord.setRemark(sapUpdateWaybillDTO.getExceptionRemark());
        tmExceptionRecord.setParentId(id);
        tmExceptionRecord.setOrderStatus(status);
        exceptionRecords.add(tmExceptionRecord);
    }

    /**
     * @param sapEnquiryVo:
     * @return R
     * @author yr
     * @description 询价单推送服务
     * @date 2022/6/30 11:10
     */
    public R inquiryFormPush(SapEnquiryVo sapEnquiryVo) {
        TMInquirySheet tmInquirySheet = BeanUtil.copy(sapEnquiryVo, TMInquirySheet.class);
        if (!Strings.isNotBlank(sapEnquiryVo.getWorkflowId())) {
            tmInquirySheet.setWorkflowId(EnquiryTypeEnum.foreignTrade.getValue());
            tmInquirySheet.setOtherRequirements(sapEnquiryVo.getDelivery());
        }
        tmInquirySheet.setQuoteStatus(InquiryStatusEnum.TO_BE_QUOTED.value());
        boolean save = iInquirySheetService.save(tmInquirySheet);
        return R.status(save);
    }
}
